/** Naive NN-ZDD with IDF
 * 
 * 
 * @author Yong Boon, Lim (yongboon.lim@gmail.com)
 */

package core;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import measure.DocumentFreq;

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.TreeMultimap;

import jdd.zdd.ZDD;

import search.FileIndexBuilder;
import search.SimpleSearchRanker;
import util.DocUtils;
import util.FileFinder;

public class NNZDDIdf extends NNZDDBasic {
	// ZDD
	DocumentFreq _dF;
	// Lucene
	
	public NNZDDIdf(String trainDataDir) {
		super(trainDataDir);
		_nnDescShort = "NN-ZDD-IDF-LUC";
		_nnDescLong = "Nearest Neighbor with ZDD Inverse Document Freq (Using Lucene to retrieve doc)";
	}
	
	@Override
	public void init() {
		super.init();
		_dF = new DocumentFreq();
	}
	
	// Convert topic to ZDD
	@Override
	public int topic2Zdd(File file) {
		String fileContent = DocUtils.ReadFile(file);
		Map<Object, Double> wordCount = DocUtils.ConvertToFeatureMapFilter(fileContent);
		int zddTopic = _zdd.base();

		for (Map.Entry<Object, Double> me : wordCount.entrySet()) {
			// If the stem word have not been created as variable
			if (!_stemVarDict.containsKey(me.getKey())) {
				int zddVar = _zdd.createVar();
				_stemVarDict.put((String) me.getKey(), zddVar);
			}
			_dF.put((String)me.getKey());
			zddTopic = changeWith(zddTopic, _stemVarDict.get(me.getKey()));
		}
		
		return zddTopic;
		
	}
	
	@Override
	public double reduceScore(int zdd, Map<Object, Double> targetWordCount) {
		// Empty Set
		if (zdd == 0)
			return _zddEmptyCost;
		// Base Set
		if (zdd == 1)
			return _zddBaseCost;

		int zddLow = _zdd.subset0(zdd, _zdd.getVar(zdd));
		int zddHigh = _zdd.subset1(zdd, _zdd.getVar(zdd));
		
		// Calculate IDF
		String word = _stemVarInvDict.get(_zdd.getVar(zdd));
//		System.out.println(word + ", " + _dF.getIDF(word));
		double zddContain = (targetWordCount.containsKey(word)) ? _dF.getIDF(word) : 0;

		double zddHighCost = reduceScore(zddHigh, targetWordCount) + zddContain;
		double zddLowCost = reduceScore(zddLow, targetWordCount);

		double zddCost = 0;
		boolean maxBranch;

		if (zddHighCost > zddLowCost) {
			zddCost = zddHighCost;
			maxBranch = true;
		} else {
			zddCost = zddLowCost;
			maxBranch = false;
		}
		_nodeMaxBranchDict.put(zdd, maxBranch);

		return zddCost;
	}
	
	@Override
	public void clear() {
		super.clear();
		_dF = null;
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		NNZDDIdf nnZDDIdf = new NNZDDIdf("data/test_data");
		nnZDDIdf.init();
		nnZDDIdf.build();
		System.out.println(nnZDDIdf.query("data/test_data/00000.txt"));

	}

}
